/*
 * gray_matrix_cl.cpp
 *
 *  Created on: 2016年2月25日
 *      Author: guyadong
 */

#include "gray_matrix_cl.h"
#include "display_tool.h"
namespace gdface {
gray_matrix_cl::gray_matrix_cl(size_t width, size_t height, int align,const cl_uchar*ptr,cl_mem_flags flags,const facecl_context &context) :
		matrix_cl(width,height,align,ptr){
	cl_mem_obj=createImage2DGray(flags,context.getContext());
}

/*
 * 从image_matrix对象构造gray_matrix_cl
 */
gray_matrix_cl::gray_matrix_cl(const image_matrix& img, cl_mem_flags flags, const facecl_context& context) :
		matrix_cl(img.width, img.height, img.align) {
	throw_if_msg(img.color_space != GFCS_GRAYSCALE, "img must be gray")
	this->v = std::vector<uint8_t>(img.pixels, img.pixels + get_image_matrix_size(img));
	this->cl_mem_obj = createImage2DGray(flags, context.getContext());
}
/*
 * 从image_matrix_v(右值)对象构造gray_matrix_cl
 */
gray_matrix_cl::gray_matrix_cl(image_matrix_v&& img, cl_mem_flags flags, const facecl_context& context) :
		matrix_cl(img.width, img.height, img.align) {
	throw_if_msg(img.color_space != GFCS_GRAYSCALE, "img must be gray")
	this->v = std::move(img.pixels);
	this->cl_mem_obj = createImage2DGray(flags, context.getContext());
}
/*
 * 从image_matrix_v(左值)对象构造gray_matrix_cl
 */
gray_matrix_cl::gray_matrix_cl(const image_matrix_v& img, cl_mem_flags flags, const facecl_context& context) :
		matrix_cl(img.width, img.height, img.align) {
	throw_if_msg(img.color_space != GFCS_GRAYSCALE, "img must be gray")
	this->v = img.pixels;
	this->cl_mem_obj = createImage2DGray(flags, context.getContext());
}

/* 缩放图像(双线性插值) */
gray_matrix_cl gray_matrix_cl::zoom(size_t dst_width, size_t dst_height, const facecl_context& context,bool download)const {
	this->check_cl_mem_obj(SOURCE_AT);
	gray_matrix_cl dst_matrix(dst_width, dst_height);
	if (tls::device_type_is(CL_DEVICE_TYPE_CPU)) {
		run_kernel(context.getKernel(KERNEL_NAME_VAR(image_scaling, ))
			, cl::EnqueueArgs(tls::command_queue()
				//每个work-group处理多行,每个work-group 的work_item数目由 IMGSCALE_LOCAL_SIZE 控制
				, cl::NDRange{ compute_num_groups(dst_matrix.height,IMGSCALE_LOCAL_SIZE)*IMGSCALE_LOCAL_SIZE }
				, cl::NDRange{ IMGSCALE_LOCAL_SIZE })
			, download
			, *this
			, dst_matrix
			, cl_float2{ 1.0f / dst_width ,1.0f / dst_height }
		);
	}	
	else {
		run_kernel(context.getKernel(KERNEL_NAME_VAR(image_scaling, ))
			, cl::EnqueueArgs(tls::command_queue()
				, cl::NDRange{ dst_height, dst_height }
				)
			, download
			, *this
			, dst_matrix
			, cl_float2{ 1.0f / dst_width ,1.0f / dst_height }
		);

	}

	return dst_matrix;
}
/*
 * 在设备中将灰度图矩阵转为cl::Buffer类型的矩阵
*/
gray_matrix_cl::matrix_cl_type gray_matrix_cl::to_matrix_cl() const {
	this->check_cl_mem_obj(SOURCE_AT);
	auto buf = cl_utilits::createBuffer(CL_MEM_READ_WRITE, this->get_mem_context(), this->width * this->height, nullptr);
	memory_cl<cl::Buffer> mat(buf, true);
	tls::command_queue().enqueueCopyImageToBuffer(this->cl_mem_obj, mat.cl_mem_obj, ZeroOffset, full_region(), 0ULL);
	return matrix_cl_type(this->width, this->height, 0, std::move(mat));
}

/*
 *  图像转置
 */
gray_matrix_cl gray_matrix_cl::transpose() const{
	auto mat = to_matrix_cl().transpose(KERNEL_NAME_VAR(matrix_transpose,_uchar));
	return gray_matrix_cl(std::move(mat));
}
/*
 * 显示图像
 */
void gray_matrix_cl::display(bool original,const std::string& title, const bool display_info, unsigned int *const XYZ,
        const bool exit_on_anykey)const{
	display_gray_matrix_cl(*this, original,title.empty()?nullptr:title.data(),display_info,XYZ,exit_on_anykey);
}
} /* namespace gdface */
